import { Button, Popconfirm } from "antd";
import { useState } from "react";
import useOnUpdated from "@/lib/hooks/useOnUpdated";
import ProgramStatus from "./ProgramStatus";
import type { IProgram, IProgramStatus } from "@/lib/types";
import { getProgramStatusSummary } from "@/lib/utils/getProgramStatusSummary";

const DefaultProgramStatus: Partial<IProgramStatus> = {
  stepHour: 1,
  stepMinute: 0,
  stepSecond: 0,
  stepIsT: "1",
  stepTSv: 23,
  stepTIsRate: "0",
  stepTIsWait: "0",
  stepIsH: "0",
  stepHSv: 0,
  stepHIsRate: "0",
  stepHIsWait: "0",
  stepIsP: "0",
  stepPSv: 0,
  stepPIsRate: "0",
  stepPIsWait: "0",
  stepTs: "00000000",
};

export type ProgramDetailProps = {
  loading?: boolean;
  program?: IProgram;
  editable?: boolean;
  programStatus?: IProgramStatus[];
  onEditRecords?: (
    record: IProgramStatus[],
    column: "循环" | "时间" | "温度" | "湿度" | "压力" | "TS",
  ) => void;
  onEditProgram?: () => void;
  isSaving?: boolean;
  onSave?: () => void;
  onUpdateProgramStatus?: (
    update: (data: IProgramStatus[]) => IProgramStatus[],
  ) => void;
};

export default function ProgramDetail(props: ProgramDetailProps) {
  const {
    loading,
    program,
    editable,
    programStatus = [],
    onEditRecords,
    onEditProgram,
    isSaving,
    onSave,
    onUpdateProgramStatus,
  } = props;
  const [totalTime, setTotalTime] = useState<string>();
  const [totalSteps, setTotalSteps] = useState<number>();
  const [totalCycle, setTotalCycle] = useState<number>();
  const [selected, setSelected] = useState<{
    type: "segment" | "step";
    records: IProgramStatus[];
  } | null>(null);

  function handleRecordsSelectionChange(
    data: {
      type: "segment" | "step";
      records: IProgramStatus[];
    } | null,
  ) {
    setSelected(data);
  }

  function handleAppendRecords() {
    const { type, records } = selected!;
    onUpdateProgramStatus?.((old) => {
      const data: IProgramStatus[] = [];
      const last = records[records.length - 1];
      let find = false;
      for (let i = 0; i < old.length; i++) {
        if (find) {
          data.push(
            type === "segment"
              ? { ...old[i], segmentNo: old[i].segmentNo + 1 }
              : old[i].segmentNo === last.segmentNo
                ? { ...old[i], stepNo: old[i].stepNo + 1 }
                : old[i],
          );
          continue;
        }
        data.push(old[i]);
        if (isSameRecord(old[i], last)) {
          find = true;
          data.push(
            (type === "segment"
              ? {
                  programId: records[0].programId,
                  segmentNo: records[0].segmentNo + 1,
                  stepNo: 1,
                  segmentLoop: 1,
                  ...DefaultProgramStatus,
                }
              : {
                  programId: records[0].programId,
                  segmentNo: records[0].segmentNo,
                  stepNo: records[0].stepNo + 1,
                  segmentLoop: records[0].segmentLoop,
                  ...DefaultProgramStatus,
                }) as IProgramStatus,
          );
        }
      }
      return data;
    });
  }
  function handleInsertRecords() {
    const { type, records } = selected!;
    onUpdateProgramStatus?.((old) => {
      const data: IProgramStatus[] = [];
      const first = records[0];
      let find = false;
      for (let i = 0; i < old.length; i++) {
        if (find) {
          data.push(
            type === "segment"
              ? { ...old[i], segmentNo: old[i].segmentNo + 1 }
              : old[i].segmentNo === first.segmentNo
                ? { ...old[i], stepNo: old[i].stepNo + 1 }
                : old[i],
          );
          continue;
        }
        data.push(old[i]);
        if (isSameRecord(old[i + 1], first)) {
          find = true;
          data.push(
            (type === "segment"
              ? {
                  programId: first.programId,
                  segmentNo: first.segmentNo,
                  stepNo: 1,
                  segmentLoop: 1,
                  ...DefaultProgramStatus,
                }
              : {
                  programId: first.programId,
                  segmentNo: first.segmentNo,
                  stepNo: first.stepNo,
                  segmentLoop: first.segmentLoop,
                  ...DefaultProgramStatus,
                }) as IProgramStatus,
          );
        }
      }
      return data;
    });
  }
  function handleDeleteRecords() {
    const { type, records } = selected!;
    onUpdateProgramStatus?.((old) => {
      if (type === "segment") {
        return old
          .filter((item) => item.segmentNo !== records[0].segmentNo)
          .map((item) =>
            item.segmentNo > records[0].segmentNo
              ? { ...item, segmentNo: item.segmentNo - 1 }
              : item,
          );
      }
      return old
        .filter((item) => !isSameRecord(item, records[0]))
        .map((item) =>
          item.segmentNo === records[0].segmentNo &&
          item.stepNo > records[0].stepNo
            ? { ...item, stepNo: item.stepNo - 1 }
            : item,
        );
    });
  }
  function handleCopyRecords() {
    const { type, records } = selected!;
    onUpdateProgramStatus?.((old) => {
      const last = records[records.length - 1];
      const newData: IProgramStatus[] = [];
      let find = false;
      for (let i = 0; i < old.length; i++) {
        if (find) {
          if (type === "segment") {
            newData.push({ ...old[i], segmentNo: old[i].segmentNo + 1 });
          } else if (old[i].segmentNo === last.segmentNo) {
            newData.push({ ...old[i], stepNo: old[i].stepNo + 1 });
          } else {
            newData.push(old[i]);
          }
          continue;
        }
        newData.push(old[i]);
        if (isSameRecord(old[i], last)) {
          if (type === "segment") {
            newData.push(
              ...records.map((item) => ({
                ...pick(item),
                segmentNo: item.segmentNo + 1,
                stepNo: item.stepNo,
                segmentLoop: item.segmentLoop,
              })),
            );
          } else {
            newData.push({
              ...pick(last),
              segmentNo: last.segmentNo,
              stepNo: last.stepNo + 1,
              segmentLoop: last.segmentLoop,
            });
          }
          find = true;
        }
      }

      return newData;
    });
  }

  useOnUpdated(() => {
    if (!program) {
      return;
    }
    // let hours = 0;
    // let mins = 0;
    // let second = 0;
    // let steps = 0;
    // programStatus.forEach((status) => {
    //   hours += status.stepHour * status.segmentLoop;
    //   mins += status.stepMinute * status.segmentLoop;
    //   second += status.stepSecond * status.segmentLoop;
    //   steps += status.segmentLoop * program!.loop;
    // });
    // mins += Math.floor(second / 60);
    // second %= 60;
    // hours += Math.floor(mins / 60);
    // mins %= 60;
    const { totalTime, totalSteps } = getProgramStatusSummary(
      programStatus,
      program.loop,
    );
    setTotalTime(totalTime);
    setTotalSteps(totalSteps);
    setTotalCycle(program.loop);
  }, [program, programStatus]);

  return (
    <div className="flex min-w-0 flex-auto flex-col px-6 pt-10">
      <div className="flex flex-none justify-end">
        <span className="mr-5">{program?.programName || "-"}</span>
        <span>总时间：{totalTime || "-"}</span>
        <span className="mx-2 self-stretch border-r border-[#797979]" />
        <span>总步数：{totalSteps || "-"}</span>
        <span className="mx-2 self-stretch border-r border-[#797979]" />
        <span>循环数：{totalCycle || "-"}</span>
      </div>
      <div className="mt-6 min-h-0 flex-auto overflow-auto">
        <ProgramStatus
          loading={loading}
          data={programStatus}
          editable={editable}
          onEditRecords={onEditRecords}
          selectable={["segment", "step"]}
          onSelectionChange={handleRecordsSelectionChange}
        />
      </div>

      {editable && (
        <div className="my-2 flex flex-none gap-x-4 rounded bg-[#262626] p-1.5">
          <Button
            className="text-xs"
            size="small"
            loading={isSaving}
            onClick={onSave}
          >
            保存
          </Button>
          <Button
            className="text-xs"
            size="small"
            disabled={!selected}
            onClick={handleAppendRecords}
          >
            添加
          </Button>
          <Button
            className="text-xs"
            size="small"
            disabled={!selected}
            onClick={handleInsertRecords}
          >
            插入
          </Button>
          <Button
            className="text-xs"
            size="small"
            disabled={!selected}
            onClick={handleCopyRecords}
          >
            复制
          </Button>
          <Popconfirm
            title="确定删除吗？"
            disabled={!selected}
            onConfirm={handleDeleteRecords}
          >
            <Button className="text-xs" size="small" disabled={!selected}>
              删除
            </Button>
          </Popconfirm>
          <Button
            className="text-xs"
            size="small"
            onClick={() => onEditProgram?.()}
          >
            循环
          </Button>
        </div>
      )}
    </div>
  );
}

function isSameRecord(a?: IProgramStatus, b?: IProgramStatus) {
  if (!a || !b) {
    return false;
  }
  return a.segmentNo === b.segmentNo && a.stepNo === b.stepNo;
}

function pick(item: IProgramStatus) {
  const res: typeof DefaultProgramStatus = {
    programId: item.programId,
  };
  for (const _key in DefaultProgramStatus) {
    const key = _key as keyof IProgramStatus;
    res[key] = item[key] as any;
  }
  return res as IProgramStatus;
}
